/**
 * Person组件
 * @param props
 * @returns {*}
 * @constructor
 */
const Person = (props) => {
    // console.log("person.props:",props)
    return (
        <div class="person-item" id={props.key}>
            <p>我是：{props.name},今年:{props.age}</p>
            <div class="btn btn-add" onClick={props.add}>添加</div>
            <div class="btn btn-delete" onClick={props.delete}>删除</div>
            <div class="btn btn-edit" onClick={props.edit}>编辑</div>
        </div>
    )
}



/**
 * App组件：父组件
 */
class App extends React.Component {
    /**
     * 1-1、挂载阶段
     * @param {*} props 
     */
    constructor(props) {
        super(props);
        this.state = {
            person: [
                { id: 0, name: "小费", age: 23 }
            ],
            name: "",
            age: "",
            count: 0,
            flag: false,
            message: ""
        }

        this.lifeCycleMounted = React.createRef()
        // console.log("this.lifecycle:",this.lifecycle)
        console.log("1-1、父组件构造方法constructor执行。")
    }
    /**
     * derive:派生
     * 1-2、挂在阶段
     * 在调用 render 方法之前调用，并且在初始挂载及后续更新时都会被调用。
     * 它应返回一个对象来更新 state，如果返回 null 则不更新任何内容
     */
    static getDerivedStateFromProps() { 
        console.log("1-2、父组件getDerivedStateFromProps方法执行。this无法货物！",this)
    }
    /**
     * 添加
     * @param index
     */
    add(index) {
        let person = this.state.person
        const item = Mock.mock({
            id: "@id",
            name: "@cname()",
            age: "@integer(20, 40)"
        })
        person.push(item)
        this.setState({
            person: person,
            name: '',
            age: '',
        })
    }

    /**
     * 删除
     * @param index
     */
    delete = (index) => {
        let person = this.state.person
        person.splice(index, 1)
        this.setState({
            person: person
        })
    }
    /**
     * 编辑
     * @param index
     */
    edit = (index) => {
        console.log(`编辑第${index}条`)
        const item = this.state.person.find((item, i) => i === index)
        console.log("item:", item)
        if (item) {
            const { person } = this.state
            const obj = Mock.mock({
                id: "@id",
                name: "@cname()",
                age: "@integer(20, 40)"
            })
            person.splice(index, 1, obj)

            this.setState({
                person: person
            })
        }

    }

    changeCount = () => {
        let count = this.state.count + 10;
        this.setState({
            count: count
        })
    }

    /**
     * react组件之间传值，不仅可以用props传值，还可以传自定义事件，通过自定义事件传值
     * @params:params参数
     */
    handleTransfer = (data) => {
        console.log("接收值prams:", data)
        let count = this.state.count + 10;
        this.setState({
            count: count,
            message: data
        })
    }

    toggleFlag = () => {
        this.setState({
            flag: !this.state.flag
        })
    }

    /**
     * 1-3、挂载阶段，完成dom渲染。
     * @returns 
     */
    render() {
        console.log("1-3、父组件render方法执行。")
        const list = this.state.person.map((item, index) =>
            <Person key={index} name={item.name} age={item.age} add={this.add.bind(this, this.state.person.length)} delete={this.delete.bind(this, index)} edit={this.edit.bind(this, index)} />
        );
        const { count } = this.state
        return (
            <div className="container">
                <div className="block">
                    <h3>0、组件生命周期函数</h3>
                    <div className="list-lifecycle" >
                        <h4>1、挂载阶段</h4>
                        <div className="lifecyle-list-mount-staged" ref={this.lifeCycleMounted}>
                            <div class="lifecycle-item">
                                1-1、父组件构造方法constructor执行。this可见,refs创建不可用,dom未创建。
                            </div>
                            <div class="lifecycle-item">
                                1-2、父组件getDerivedStateFromProps方法执行，this不可见。
                            </div>
                            <div class="lifecycle-item">
                                1-3、父组件父组件render方法执行，this可见，dom创建成功。
                            </div>
                        </div>
                    </div>
                </div>
                <div className="block">
                    <h3>1、组件间传值示例：</h3>
                    <div className="count" style={{ margin: '10px 0' }}>App的值 : {count}</div>
                    <div className="btn btn-edit" onClick={this.changeCount}>修改count</div>
                    <div className="message"> {this.state.message} </div>
                    {/*子组件*/}
                    <ChildComponent count={count} onHandleTransfer={this.handleTransfer} />
                </div>
                <div className="block info">
                    <h3>2、个人信息增删改查：</h3>
                    {list}
                </div>

                <div className="block">
                    <h3>3、react事件state切换状态：</h3>
                    <div className="result">
                        {
                            this.state.flag ?
                                <div className="info">孙悟空</div> :
                                <div className="info">六耳猕猴</div>
                        }
                        <div className="btn btn-edit" onClick={this.toggleFlag}>切换状态</div>
                    </div>
                </div>
            </div>
        )
    }
    /**
     * 1-4、挂载阶段
     */
    componentDidMount() {
        console.log("1-4、父组件componentDidMount方法执行。")
        const el = this.lifeCycleMounted.current
        el.innerHTML += `<div class="lifecycle-item">
                            1-4、父组件构造方法父组件componentDidMount方法执行执行。this可见, refs创建可用。
                        </div>`
    }
    componentWillUnmount() { 
        console.log("1-4、父组件componentWillUnmount方法执行。")
    }

    
}

/**
 * 子组件：获取props和父组件事件
 * @param props
 * @returns {*}
 * @constructor
 */
class ChildComponent extends React.Component {

    /**
     * 2-1、挂载阶段
     * @param {*} props 
     */
    constructor(props) {
        super(props);
        this.state = {
            count: this.props.count
        }
        console.log("2-1、子组件构方法constructor执行。")
    }
    /**
     * 2-1、挂载阶段、更新阶段
     * 
     * @param {*} props 
     */
    static getDerivedStateFromProps() {
        console.log("2-2、子组件getDerivedStateFromProps方法执行。")
    }

    componentWillMount() {
        console.log("2-3、组件即将挂载，componentWillMount执行。")
    }
    /**
     * 2-3、更新阶段
     */
    componentDidMount() {
        console.log("2-3、组件挂载完成，componentDidMount执行。")
    }

    /**
     * prop改变
     */
    componentWillReceiveProps() {
        console.log("组件props值发生改变，视图开始更新")
    }

    shouldComponentUpdate() {
        console.log("组件要更新吗？")
    }
    componentWillUpdate() {
        console.log("组件将要更新")
    }
    componentDidUpdate() {
        console.log("组件更新完成")
    }
    componentWillUnmount() {
        console.log("组件卸载")
    }

    sendHandle = () => {
        this.props.onHandleTransfer("子组件发送事件参数")
    }

    render() {
        return (
            <div className="child-block">
                <h3>子组件修改示例父组件传过来的值：通过父组件的事件</h3>
                <div className="count" style={{ margin: '10px 0' }}>子组件接收的值 : {this.props.count}</div>
                <div className="btn btn-edit" onClick={this.sendHandle}>子组件修改count</div>
            </div>
        )
    }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
